package com.pai4j.act.service;

import com.google.common.collect.Lists;
import com.pai4j.act.repository.dao.IResourceBehaviorDAO;
import com.pai4j.act.repository.entity.ResourceBehaviorEntity;
import com.pai4j.common.constants.ResourceBehaviorConstants;
import com.pai4j.common.exception.BusinessException;
import com.pai4j.common.service.messagequeue.producer.MessageQueueProducer;
import com.pai4j.common.util.DateUtils;
import com.pai4j.common.util.RedisUtil;
import com.pai4j.domain.vo.request.mess.MessageNotifyVO;
import com.pai4j.domain.vo.response.UserBaseResponseInfoVO;
import com.pai4j.remote.pgc.SubjectArticleClient;
import com.pai4j.remote.ugc.MomentClient;
import com.pai4j.domain.vo.response.moment.MomentVO;
import com.pai4j.domain.vo.response.subjectaccount.ArticleBaseResponseVO;
import com.pai4j.common.enums.InteractionMessageTypeEnum;
import com.pai4j.common.enums.MessageTypeEnum;
import com.pai4j.common.enums.messagequeue.MessageBroadChannelEnum;
import com.pai4j.common.bean.PAIResponseBean;
import com.pai4j.common.bean.PAIResponseBeanUtil;
import lombok.extern.slf4j.Slf4j;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.ZSetOperations;
import com.pai4j.common.enums.RedisKeyEnum;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public abstract class AbstractResourceBehaviorService implements ResourceBehaviorInter {

    protected String behaviorType;
    protected String behaviorTypeName;
    public void setBehaviorType(String behaviorType) {
        this.behaviorType = behaviorType;
        this.behaviorTypeName = ResourceBehaviorConstants.getBehaviorTypeName(behaviorType);
    }

    @Resource
    IResourceBehaviorDAO resourceBehaviorDAO;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RedissonClient redissonClient;
    @Autowired
    private AccountService accountService;
    @Autowired
    private MessageQueueProducer<MessageNotifyVO, Long> messageQueueProducer;
    @Autowired
    private SubjectArticleClient subjectArticleClient;
    @Autowired
    private MomentClient momentClient;

    /**
     * 实际互动行为，由具体实现类来实现
     *
     * @param userId
     * @param resourceType
     * @param resourceId
     * @return
     */
    protected abstract boolean doBehavior(String userId, String resourceType, Long resourceId);

    /**
     * 实际取消互动行为，由具体实现类来实现
     *
     * @param userId
     * @param resourceType
     * @param resourceId
     * @return
     */
    protected boolean doCancelBehavior(String userId, String resourceType, Long resourceId) {

        throw new BusinessException("不支持的互动行为");
    }

    @Override
    public long behavior(String userId, String resourceType, Long resourceId) {

        Long behaviorCount = 0L;
        /**
         * 1. 数据持久化 DB
         */
        if (this.doBehavior(userId, resourceType, resourceId)) {

            /**
             * 2. 构建、刷新互动行为数据缓存
             */
            behaviorCount = this.refreshBehaviorCache(userId, resourceType, resourceId, false);
            /**
             * 3. 互动消息通知
             */
            this.sendInteractionNotification(userId, resourceType, resourceId);

        }
        return behaviorCount;
    }

    @Override
    public long cancelBehavior(String userId, String resourceType, Long resourceId) {
        Long behaviorCount = 0L;
        /**
         * 1. 数据持久化 DB
         */
        if (this.doCancelBehavior(userId, resourceType, resourceId)) {
            /**
             * 2. 构建、刷新互动行为数据缓存
             */
            behaviorCount = this.refreshBehaviorCache(userId, resourceType, resourceId, true);
        }
        return behaviorCount;
    }


    /**
     * 批量查询资源的互动数量
     *
     * @param resourceType
     * @param resourceIds
     * @return
     */
    @Override
    public Map<Long, Long> countBehavior(String resourceType, List<Long> resourceIds) {
        Map<Long, Long> behaviorCountMap = new HashMap<>();
        String behaviorCacheKey = resourceBehaviorCountCacheHashKey(resourceType);
        List<String> resourceIdArr = resourceIds.stream().map(String::valueOf).collect(Collectors.toList());
        List<String> caches = redisUtil.hmget(behaviorCacheKey, resourceIdArr);
        for (int i = 0; i < resourceIds.size(); i++) {
            Long resourceId = resourceIds.get(i);
            String cache = caches.get(i);
            Long count;
            if (StringUtils.isNotBlank(cache)) {
                count = Long.valueOf(cache);
            } else {
                // TODO 推荐大家遍历结束后批量刷新
                count = this.initRefreshBehaviorCache(resourceType, resourceId);
            }
            behaviorCountMap.put(resourceId, count);
        }
        return behaviorCountMap;
    }
    /**
     * 检查用户对指定资源的行为状态: 用于判断该用户是否已经对资源进行某些行为
     * 
     * @param userId 用户ID
     * @param resourceType 资源类型
     * @param resourceIds 资源ID列表
     * @return Map<Long, Boolean> 资源ID与行为状态的映射关系，key为资源ID，value为是否具有行为状态
     */
    @Override
    public Map<Long, Boolean> isBehavior(String userId, String resourceType, List<Long> resourceIds) {

        // 构造用户行为资源缓存键
        String cacheKey = this.userBehaviorResourceCacheKey(userId, resourceType);
        if(!redisUtil.exists(cacheKey)) {
            // 如果缓存不存在，则初始化用户行为资源缓存
            this.initUserBehaviorResourcesCache(userId, resourceType);
        }
        
        // 将资源ID列表转换为字符串集合
        Set<String> resourceIdSet = resourceIds.stream().map(String::valueOf).collect(Collectors.toSet());
        
        // 从Redis中批量检查资源ID是否存在
        Map<String, Boolean> behaviorStatusMap = redisUtil.zContains(cacheKey, resourceIdSet);
        
        // 将结果转换为Long类型的键并返回
        return behaviorStatusMap.entrySet().stream()
                .collect(Collectors.toMap(
                        entry -> Long.parseLong(entry.getKey()),
                        Map.Entry::getValue,
                        (existing, replacement) -> existing
                ));
    }

    /**
     * 判断用户对指定资源是否有行为权限
     * 
     * @param userId 用户ID
     * @param resourceType 资源类型
     * @param resourceId 资源ID
     * @return 如果用户对资源有行为权限则返回true，否则返回false
     */
    public boolean isBehavior(String userId, String resourceType, Long resourceId) {
        // 调用批量判断方法，传入单个资源ID的列表
        Map<Long, Boolean> isBehaviorMap = this.isBehavior(userId, resourceType, Lists.newArrayList(resourceId));
        // 从结果Map中获取对应资源ID的权限状态并返回
        return ObjectUtils.equals(isBehaviorMap.get(resourceId), true);
    }
    
    
    public Long countBehavior(String resourceType, Long resourceId) {
        // 调用批量判断方法，传入单个资源ID的列表
        Map<Long, Long> countBehaviorMap = this.countBehavior(resourceType, Lists.newArrayList(resourceId));
        // 从结果Map中获取对应资源ID的权限状态并返回
        return countBehaviorMap.get(resourceId);
    }
    
    
    /**
     * 刷新行为缓存
     * 
     * @param userId       用户ID
     * @param resourceType 资源类型
     * @param resourceId   资源ID
     * @param isCancel     是否取消操作
     * @return 行为计数
     */
    private Long refreshBehaviorCache(String userId, String resourceType, Long resourceId, boolean isCancel) {

        /**
         * 1. 刷新资源互动总量
         */
        Long behaviorCount = this.refreshBehaviorCountCache(resourceType, resourceId, isCancel);
        /**
         * 2. 刷新用户维度操作过的资源列表缓存
         */
        this.refreshUserBehaviorResourcesCache(userId, resourceType, resourceId, isCancel);
        /**
         * 3. 刷新资源维度操作过的用户列表缓存
         */
        this.refreshResourceBehaviorUsersCache(userId, resourceType, resourceId, isCancel);
        return behaviorCount;
    }



    /**
     * 刷新用户维度，互动资料列表缓存
     *
     * 这里为什么使用Zset，而不是Set？
     * 因为我们考虑到后续在”个人中心这一场景下，我们需要分页获取指定用户互动过的有序资源列表“
     *
     * @param userId
     * @param resourceType
     * @param resourceId
     * @param isCancel
     */
    private void refreshUserBehaviorResourcesCache(String userId, String resourceType, Long resourceId, boolean isCancel) {
        String cacheKey = this.userBehaviorResourceCacheKey(userId, resourceType);
        if (!redisUtil.exists(cacheKey)) {
            RLock lock = redissonClient.getLock(RedisKeyEnum.USER_BEHAVIOR_RESOURCE_CACHE_INIT_LOCK.getKey(userId));
            try {
                lock.lock();
                // 双重检查锁，避免并发下重复查库刷新redis
                if (!redisUtil.exists(cacheKey)) {
                    this.initUserBehaviorResourcesCache(userId, resourceType);
                }
            } finally {
                lock.unlock();
            }
            return;
        }
        if (isCancel) {
            // 取消互动
            redisUtil.zremove(cacheKey, String.valueOf(resourceId));
            return;
        }
        redisUtil.zadd(cacheKey, String.valueOf(resourceId), DateUtils.getCurrentTimeMillis(),
                RedisKeyEnum.USER_BEHAVIOR_RESOURCE_ZSET_CACHE.getExpireTime());
    }
    /**
     * 初始化用户行为资源缓存
     * <p>
     * 根据用户ID和资源类型从数据库查询用户行为数据，将查询结果构造成有序集合(ZSet)存储到Redis中。
     * 缓存的成员为资源索引，分数为行为记录的更新时间或创建时间的时间戳。
     *
     * @param userId       用户ID
     * @param resourceType 资源类型
     */
    private void initUserBehaviorResourcesCache(String userId, String resourceType) {
        // 查询用户指定资源类型下的所有行为记录
        List<ResourceBehaviorEntity> entities =
                resourceBehaviorDAO.findAllByUserBehaviorResource(userId, behaviorType, resourceType);
        if (CollectionUtils.isNotEmpty(entities)) {
            // 构造有序集合元素集合，成员为资源索引，分数为时间戳
            Set<ZSetOperations.TypedTuple<String>> typedTupleSet = new HashSet<>();
            for (ResourceBehaviorEntity resourceBehavior : entities) {
                String value = String.valueOf(resourceBehavior.getResourceIndex());
                double score = resourceBehavior.getUpdateDate() != null ?
                               resourceBehavior.getUpdateDate().getTime() : resourceBehavior.getCreateDate().getTime();
                ZSetOperations.TypedTuple<String> tuple = new DefaultTypedTuple<>(value, score);
                typedTupleSet.add(tuple);
            }
            // 构造缓存键并写入Redis有序集合
            String cacheKey = this.userBehaviorResourceCacheKey(userId, resourceType);
            redisUtil.zadd(cacheKey, typedTupleSet, RedisKeyEnum.USER_BEHAVIOR_RESOURCE_ZSET_CACHE.getExpireTime());
        }
    }

    /**
     * 初始化资源行为用户缓存
     * <p>
     * 根据资源ID和资源类型从数据库查询资源的用户行为数据，将查询结果构造成有序集合(ZSet)存储到Redis中。
     * 缓存的成员为用户ID，分数为行为记录的更新时间或创建时间的时间戳。
     *
     * @param resourceId   资源ID
     * @param resourceType 资源类型
     */
    private void initResourceBehaviorUsersCache(Long resourceId, String resourceType) {
        // 查询资源指定资源类型下的所有用户行为记录
        List<ResourceBehaviorEntity> entities =
                resourceBehaviorDAO.findAllByResourceBehaviorUser(resourceId, behaviorType, resourceType);
        if (CollectionUtils.isNotEmpty(entities)) {
            // 构造有序集合元素集合，成员为用户ID，分数为时间戳
            Set<ZSetOperations.TypedTuple<String>> typedTupleSet = new HashSet<>();
            for (ResourceBehaviorEntity resourceBehavior : entities) {
                String value = String.valueOf(resourceBehavior.getUserId());
                double score = resourceBehavior.getUpdateDate() != null ?
                        resourceBehavior.getUpdateDate().getTime() : resourceBehavior.getCreateDate().getTime();
                ZSetOperations.TypedTuple<String> tuple = new DefaultTypedTuple<>(value, score);
                typedTupleSet.add(tuple);
            }
            // 构造缓存键并写入Redis有序集合
            String cacheKey = this.resourceBehaviorUserCacheKey(resourceId, resourceType);
            redisUtil.zadd(cacheKey, typedTupleSet, RedisKeyEnum.RESOURCE_BEHAVIOR_USER_ZSET_CACHE.getExpireTime());
        }
    }

    /**
     * 获取资源行为用户信息
     * @return
     */
    public Map<String, UserBaseResponseInfoVO> getResourceBehaviorUsersCache(Long resourceId,String resourceType){
        HashMap<String, UserBaseResponseInfoVO> resourceBehaviorMap = new HashMap<>();
        String cacheKey = this.resourceBehaviorUserCacheKey(resourceId, resourceType);
        // 缓存不存在时尝试初始化（轻量级兜底，避免首次读取为空）
        if (!redisUtil.exists(cacheKey)) {
            this.initResourceBehaviorUsersCache(resourceId, resourceType);
        }
        // 使用ZSet读取用户列表，保持与写入一致的数据结构
        Set<String> userIdList = redisUtil.zSetGetAll(cacheKey);
        if (org.apache.commons.collections.CollectionUtils.isEmpty(userIdList)) {
            return resourceBehaviorMap;
        }
        for (String userId : userIdList) {
            UserBaseResponseInfoVO userBaseResponseInfoVO = accountService.accountInfo(userId);
            // 以用户ID作为key，返回用户基本信息
            resourceBehaviorMap.put(userId, userBaseResponseInfoVO);
        }
        return resourceBehaviorMap;
    }

    /**
     * 刷新资源行为用户缓存
     * <p>
     * 该方法用于维护资源行为用户缓存，包括初始化缓存、添加用户行为记录和取消用户行为记录。
     * 使用Redis的有序集合(ZSet)存储用户行为数据，以用户ID为成员，以当前时间戳为分数。
     * 通过Redisson分布式锁保证缓存初始化的线程安全。
     *
     * @param userId 用户ID，表示执行行为的用户
     * @param resourceType 资源类型，用于区分不同类型的资源
     * @param resourceId 资源ID，标识具体资源的唯一ID
     * @param isCancel 是否取消操作，true表示取消用户对该资源的行为，false表示添加用户行为
     */
    private void refreshResourceBehaviorUsersCache(String userId, String resourceType, Long resourceId, boolean isCancel) {
        String cacheKey = this.resourceBehaviorUserCacheKey(resourceId, resourceType);
        // 检查缓存是否存在，不存在则需要初始化
        if (!redisUtil.exists(cacheKey)) {
            // 获取分布式锁，防止并发情况下重复查询数据库初始化缓存
            RLock lock = redissonClient.getLock(RedisKeyEnum.RESOURCE_BEHAVIOR_USER_CACHE_INIT_LOCK.getKey(
                    resourceType, String.valueOf(resourceId)));
            try {
                lock.lock();
                // 双重检查锁，避免并发下重复查库刷新redis
                if (!redisUtil.exists(cacheKey)) {
                    this.initResourceBehaviorUsersCache(resourceId, resourceType);
                }
            } finally {
                lock.unlock();
            }
            return;
        }
        // 根据操作类型执行相应的缓存更新
        if (isCancel) {
            // 取消互动，从有序集合中移除指定用户
            redisUtil.zremove(cacheKey, userId);
            return;
        }
        // 添加用户行为记录到有序集合中，分数为当前时间戳
        redisUtil.zadd(cacheKey, userId, DateUtils.getCurrentTimeMillis(),
                RedisKeyEnum.USER_BEHAVIOR_RESOURCE_ZSET_CACHE.getExpireTime());
    }


    /**
     * 基于redis hash结构的原子+-特性实现计数器，记录资源互动最新量
     *
     * @param resourceType
     * @param resourceId
     * @param isCancel
     * @return
     */
    private Long refreshBehaviorCountCache(String resourceType, Long resourceId, boolean isCancel) {
        String cacheKey = this.resourceBehaviorCountCacheHashKey(resourceType);
        Long behaviorCount;
        if (isCancel) {
            behaviorCount = redisUtil.hdecrex(cacheKey, String.valueOf(resourceId));
        } else {
            behaviorCount = redisUtil.hincrex(cacheKey, String.valueOf(resourceId));
        }
        redisUtil.expire(cacheKey, RedisKeyEnum.RESOURCE_BEHAVIOR_COUNT_CACHE.getExpireTime());
        if (behaviorCount == 1 || behaviorCount == 0) {
            // 说明：之前没有互动或者redis过期，都重新查库初始化一次redis缓存
            behaviorCount = this.initRefreshBehaviorCache(resourceType, resourceId);
        }
        return behaviorCount;
    }
    
    /**
     * 初始化资源行为计数缓存
     * 
     * @param resourceType 资源类型
     * @param resourceId 资源ID
     * @return 行为计数
     */
    private Long initRefreshBehaviorCache(String resourceType, Long resourceId) {
        // 查询指定资源的行为计数
        Long behaviorCount = resourceBehaviorDAO.countByBehaviorTypeAndResourceTypeAndResourceIndexAndStatusTrue(
                behaviorType, resourceType, resourceId);
        // 构造缓存hash key
        String countHashKey = this.resourceBehaviorCountCacheHashKey(resourceType);
        // 将行为计数存入redis缓存
        redisUtil.hset(countHashKey, String.valueOf(resourceId), String.valueOf(behaviorCount),
                RedisKeyEnum.RESOURCE_BEHAVIOR_COUNT_CACHE.getExpireTime());
        return behaviorCount;
    }

    /**
     * 构造资源行为计数缓存的hash key
     * 
     * @param resourceType 资源类型
     * @return 缓存key
     */
    private String resourceBehaviorCountCacheHashKey(String resourceType) {
        return RedisKeyEnum.RESOURCE_BEHAVIOR_COUNT_CACHE.getKey(this.behaviorType, resourceType);
    }
  
    /**
     * 构造用户行为资源缓存key
     * 
     * @param userId 用户ID
     * @param resourceType 资源类型
     * @return 缓存key
     */
    private String userBehaviorResourceCacheKey(String userId, String resourceType) {
        return RedisKeyEnum.USER_BEHAVIOR_RESOURCE_ZSET_CACHE.getKey(behaviorType, resourceType, userId);
    }

    /**
     * 构造资源行为用户缓存key
     * 
     * @param resourceId 资源ID
     * @param resourceType 资源类型
     * @return 缓存key
     */
    private String resourceBehaviorUserCacheKey(Long resourceId, String resourceType) {
        return RedisKeyEnum.USER_BEHAVIOR_RESOURCE_ZSET_CACHE.getKey(behaviorType, resourceType, String.valueOf(resourceId));
    }
    
    /**
     * 发送互动通知消息
     *
     * @param userId       行为执行者用户ID
     * @param resourceType 资源类型
     * @param resourceId   资源ID
     */
    private void sendInteractionNotification(String userId, String resourceType, Long resourceId) {
        try {
            // 获取资源拥有者
            String resourceOwner = getResourceOwner(resourceType, resourceId);
            if (StringUtils.isBlank(resourceOwner)) {
                return;
            }
            
            // 不给自己发送通知
            if (ObjectUtils.equals(userId, resourceOwner)) {
                return;
            }
            
            // 获取行为执行者信息
            UserBaseResponseInfoVO senderInfo = accountService.accountInfo(userId);
            if (senderInfo == null) {
                return;
            }
            
            // 构建通知消息
            MessageNotifyVO messageNotifyVO = new MessageNotifyVO();
            messageNotifyVO.setSenderId(userId);
            messageNotifyVO.setReceiverId(resourceOwner);
            messageNotifyVO.setSender(senderInfo);
            messageNotifyVO.setTime(DateUtils.getCurrentTimeMillis());
            messageNotifyVO.setType(MessageTypeEnum.INTERACTION.getType());
            
            // 设置互动消息类型（将行为类型转换为互动消息类型）
            InteractionMessageTypeEnum interactionType = InteractionMessageTypeEnum.fromBehaviorType(behaviorType);
            messageNotifyVO.setMessageType(interactionType.getCode());
            log.debug("互动消息类型设置: behaviorType={}, messageType={}", behaviorType, interactionType.getCode());
            
            // 设置被互动的资源信息
            messageNotifyVO.setResourceId(resourceId);
            messageNotifyVO.setResourceType(resourceType);
            
            // 获取并设置资源详细信息（标题、封面图、跳转链接、image字段）
            fillResourceDetails(messageNotifyVO, resourceType, resourceId);
            
            // 构建消息内容（包含资源标题）
            String message = buildNotificationMessage(senderInfo.getUserName(), behaviorTypeName, 
                    resourceType, messageNotifyVO.getResourceTitle());
            messageNotifyVO.setMessage(message);
            
            // 发送通知
            messageQueueProducer.broadSend(MessageBroadChannelEnum.QUEUE_INTERACTION_NOTIFY, messageNotifyVO);
            
        } catch (Exception e) {
            // 通知发送失败不影响主业务，只记录日志
            log.error("发送互动通知失败: userId={}, resourceType={}, resourceId={}", userId, resourceType, resourceId, e);
        }
    }
    
    /**
     * 根据资源类型获取资源拥有者
     *
     * @param resourceType 资源类型
     * @param resourceId   资源ID
     * @return 资源拥有者用户ID
     */
    private String getResourceOwner(String resourceType, Long resourceId) {
        try {
            switch (resourceType) {
                case "MOMENT":
                    PAIResponseBean<MomentVO> momentResponse = momentClient.detail(resourceId);
                    if (PAIResponseBeanUtil.isOk(momentResponse) && momentResponse.getData() != null) {
                        return momentResponse.getData().getAuthor();
                    }
                    break;
                case "ARTICLE":
                    PAIResponseBean<ArticleBaseResponseVO> articleResponse = subjectArticleClient.detail(resourceId, false);
                    if (PAIResponseBeanUtil.isOk(articleResponse) && articleResponse.getData() != null) {
                        return articleResponse.getData().getAuthor();
                    }
                    break;
                    /**
                case "COURSE":
                    PAIResponseBean<CourseBaseResponseVO> courseResponse = courseClient.detail(resourceId, false);
                    if (PAIResponseBeanUtil.isOk(courseResponse) && courseResponse.getData() != null) {
                        return courseResponse.getData().getAuthor();
                    }
                     break;
                     */
                default:
                    // 其他资源类型可以在这里扩展
                    break;
            }
        } catch (Exception e) {
            log.error("获取资源拥有者失败: resourceType={}, resourceId={}", resourceType, resourceId, e);
        }
        return null;
    }
    
    /**
     * 填充资源详细信息（包括标题、封面图、跳转链接、image字段）
     *
     * @param messageNotifyVO 消息通知VO
     * @param resourceType    资源类型
     * @param resourceId      资源ID
     */
    private void fillResourceDetails(MessageNotifyVO messageNotifyVO, String resourceType, Long resourceId) {
        try {
            switch (resourceType) {
                case "MOMENT":
                    PAIResponseBean<MomentVO> momentResponse = momentClient.detail(resourceId);
                    if (PAIResponseBeanUtil.isOk(momentResponse) && momentResponse.getData() != null) {
                        MomentVO moment = momentResponse.getData();
                        // 设置动态内容摘要作为标题（截取前50个字符）
                        if (StringUtils.isNotBlank(moment.getContent())) {
                            String title = moment.getContent();
                            if (title.length() > 50) {
                                title = title.substring(0, 47) + "...";
                            }
                            messageNotifyVO.setResourceTitle(title);
                        }
                        // 设置封面图（取第一张图片）
                        if (CollectionUtils.isNotEmpty(moment.getImages())) {
                            String imageUrl = String.valueOf(moment.getImages().get(0));
                            messageNotifyVO.setResourceImage(imageUrl);
                            // 同时设置image字段，用于消息列表展示
                            messageNotifyVO.setImage(imageUrl);
                        }
                        // 设置跳转链接
                        messageNotifyVO.setResourceUrl("/moment/detail/" + resourceId);
                    }
                    break;
                    
                case "ARTICLE":
                    PAIResponseBean<ArticleBaseResponseVO> articleResponse = subjectArticleClient.detail(resourceId, false);
                    if (PAIResponseBeanUtil.isOk(articleResponse) && articleResponse.getData() != null) {
                        ArticleBaseResponseVO article = articleResponse.getData();
                        // 设置文章标题
                        messageNotifyVO.setResourceTitle(article.getTitle());
                        // 设置文章封面图（防止cover为null导致空指针）
                        if (article.getCover() != null) {
                            String coverUrl = article.getCover().toString();
                            messageNotifyVO.setResourceImage(coverUrl);
                            // 同时设置image字段，用于消息列表展示
                            messageNotifyVO.setImage(coverUrl);
                        }
                        // 设置跳转链接
                        messageNotifyVO.setResourceUrl("/article/detail/" + resourceId);
                    }
                    break;
                    
                /**
                case "COURSE":
                    PAIResponseBean<CourseBaseResponseVO> courseResponse = courseClient.detail(resourceId, false);
                    if (PAIResponseBeanUtil.isOk(courseResponse) && courseResponse.getData() != null) {
                        CourseBaseResponseVO course = courseResponse.getData();
                        messageNotifyVO.setResourceTitle(course.getTitle());
                        if (course.getCoverImage() != null) {
                            messageNotifyVO.setResourceImage(course.getCoverImage());
                            messageNotifyVO.setImage(course.getCoverImage());
                        }
                        messageNotifyVO.setResourceUrl("/course/detail/" + resourceId);
                    }
                    break;
                */
                    
                default:
                    // 其他资源类型可以在这里扩展
                    log.debug("未知的资源类型: {}", resourceType);
                    break;
            }
        } catch (Exception e) {
            log.warn("填充资源详细信息失败: resourceType={}, resourceId={}", resourceType, resourceId, e);
        }
    }
    
    /**
     * 构建通知消息内容
     *
     * @param senderName       行为执行者姓名
     * @param behaviorTypeName 行为类型名称
     * @param resourceType     资源类型
     * @param resourceTitle    资源标题
     * @return 通知消息内容
     */
    private String buildNotificationMessage(String senderName, String behaviorTypeName, 
                                           String resourceType, String resourceTitle) {
        String resourceTypeName;
        switch (resourceType) {
            case "MOMENT":
                resourceTypeName = "π圈动态";
                break;
            case "ARTICLE":
                resourceTypeName = "文章";
                break;
            case "COURSE":
                resourceTypeName = "课程";
                break;
            default:
                resourceTypeName = "内容";
                break;
        }
        
        // 如果有资源标题，则包含在消息中
        if (StringUtils.isNotBlank(resourceTitle)) {
            return String.format("%s %s了你的%s《%s》", senderName, behaviorTypeName, resourceTypeName, resourceTitle);
        } else {
            return String.format("%s %s了你的%s", senderName, behaviorTypeName, resourceTypeName);
        }
    }

}
